package zcj.succ.limitdownload.controller;


import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import zcj.succ.limitdownload.aspect.PreventRepeatCommit;
import zcj.succ.limitdownload.constant.StorageUnitEnum;

import java.io.*;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping("download/folder")
public class DownloadApi {
    private final int downspeed;

    @RequestMapping(value = "/test",method = RequestMethod.GET)
    public void test(){
        int i=1/0;
    }
    @PreventRepeatCommit(duration = 10,unit = TimeUnit.SECONDS,message = "不允许重复提交，请稍后再试")
    @RequestMapping(value = "/path", method = RequestMethod.GET)
    public String downZip(@RequestParam(name ="abPath",defaultValue ="") String abPath, HttpServletResponse response){
        File folder = new File(abPath);
        if (!folder.exists()||!folder.isDirectory()||!folder.canRead()) {
            return "目录不存在或无权限，无法进行下载" ;
        }
        try(ServletOutputStream outputStream= response.getOutputStream()) {
            //设置响应体格式
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            //设置响应头信息 以附件形式响应 名字为folder.zip
            response.setHeader("Content-Disposition", "attachment; filename=\"folder.zip\"");
            //创建压缩包输出利流
            ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
            //压缩文件夹 并输出到前端
            compress(folder, folder.getName(), zipOutputStream,new byte[1024]);
            zipOutputStream.close();
            response.flushBuffer();
            return "success,请等待下载完成!!!";
        } catch (IOException | InterruptedException e) {
            //记录日志
            return "error";
        }
    }

    /**
     * 辅助方法 返回压缩后的文件
     * @param folder
     * @param filename
     * @param zipOutputStream
     */

    private long start=0;
    private int totalLen=0;
    private void compress(File folder, String filename, ZipOutputStream zipOutputStream,byte[]buffer) throws IOException, InterruptedException {
            //如果该文件是文件夹的话 进行处理
            if(folder.isDirectory()){
                //判断文件夹后没有 / 就给它加上
                if(!filename.endsWith("/")){
                    filename=filename.concat("/");
                }
                //将文件夹加入到压缩包
                zipOutputStream.putNextEntry(new ZipEntry(filename));
                zipOutputStream.closeEntry();
                //递归处理子文件夹
                File[] childFiles = folder.listFiles();
                if(null!=childFiles){
                    for (File cf : childFiles) {
                        compress(cf,filename+cf.getName(),zipOutputStream,buffer);
                    }
                }
            }else{//不是文件夹 需要写入
                FileInputStream fis = new FileInputStream(folder);
                //将文件加入到压缩包写入
                zipOutputStream.putNextEntry(new ZipEntry(filename));
                int length;
                while ((length = fis.read(buffer)) >= 0) {
                    zipOutputStream.write(buffer, 0, length);
                    totalLen+=length;
                    if(totalLen>=downspeed){
                        long end = System.currentTimeMillis();
                        long wait=1000-(end-start);
                        if(wait>0){
                            Thread.sleep(wait);
                        }
                        start=System.currentTimeMillis();
                        totalLen=0;
                    }
                }
                zipOutputStream.closeEntry();
                fis.close();
            }
    }
    public DownloadApi(@Value("${system.download.limit.downloadSymbol}") String downloadSymbol) {
        //判空
        if(Objects.isNull(downloadSymbol)||"".equals(downloadSymbol)){
            downspeed=1024;
            return;
        }
        //定义正则
        Pattern pattern = Pattern.compile("(\\d+)([A-Za-z]+)");
        //截取匹配
        Matcher matcher = pattern.matcher(downloadSymbol);
        //找组
        boolean isFind = matcher.find();
        String letterPart = matcher.group(2);
        int num = Integer.parseInt(matcher.group(1));
        if(StorageUnitEnum.BYTE.name.equals(letterPart)){
            downspeed=num*StorageUnitEnum.BYTE.value;
        }else if(StorageUnitEnum.KB.name.equals(letterPart)){
            downspeed=num*StorageUnitEnum.KB.value;
        }else if(StorageUnitEnum.MB.name.equals(letterPart)){
            downspeed=num*StorageUnitEnum.MB.value;
        }else{
            downspeed=1024;
        }
    }
}
